package com.bgh.dynobot;

import static android.hardware.SensorManager.DATA_X;
import static android.hardware.SensorManager.DATA_Y;
import static android.hardware.SensorManager.DATA_Z;
import static android.hardware.SensorManager.SENSOR_ACCELEROMETER;
import static android.hardware.SensorManager.SENSOR_DELAY_UI;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class GForces extends Activity implements SensorListener, OnClickListener {
	private SensorManager sensorMgr;
	private TextView accuracyLabel;
	private Button calibrateButton;
	private float x, y, z;
	private GForceView mView;
	private TextView currentGTV, maxAccelerationGTV, maxBrakeGTV;
	double angle, maxAccelerationAngle, maxBrakeAngle = 0;
	float G, maxAccelerationG, maxBrakeG = 0;
    double maxUnits = 1.5;
    private long lastUpdate = -1;
	// deltas for calibration
	private float cx, cy, cz;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.gforces);  
        mView = new GForceView(this);
        LinearLayout l = (LinearLayout) findViewById(R.id.gforces_layout);
        currentGTV = (TextView) findViewById(R.id.currentG);
        maxAccelerationGTV = (TextView) findViewById(R.id.maxAccelerationG);
        maxBrakeGTV = (TextView) findViewById(R.id.maxBrakeG);
        l.addView(mView);
    }

	@Override
	protected void onPause() {
		super.onPause();
		
		sensorMgr.unregisterListener(this, SENSOR_ACCELEROMETER);
		sensorMgr = null;
		
		cx = 0;
		cy = 0;
		cz = 0;
	}
	

	@Override
	protected void onResume() {
		super.onResume();
		
		sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
		boolean accelSupported = sensorMgr.registerListener(this, 
				SENSOR_ACCELEROMETER,
				SENSOR_DELAY_UI);
		
		if (!accelSupported) {
			// on accelerometer on this device
			sensorMgr.unregisterListener(this, SENSOR_ACCELEROMETER);
			accuracyLabel.setText(R.string.no_accelerometer);
		}
	}

	// from the android.hardware.SensorListener interface
	public void onAccuracyChanged(int sensor, int accuracy) {
		// this method is called very rarely, so we don't have to
		// limit our updates as we do in onSensorChanged(...)
		// this method is called very rarely, so we don't have to
		// limit our updates as we do in onSensorChanged(...)
	}
	
	// from the android.hardware.SensorListener interface
	public void onSensorChanged(int sensor, float[] values) {
		if (sensor == SENSOR_ACCELEROMETER) {
			G = 0;
            angle = 0;
            long curTime = System.currentTimeMillis();
            
            if(Math.abs(x) > Math.abs(y)){
            	G = Math.abs(x)/SensorManager.GRAVITY_EARTH;
            }else{
            	G = Math.abs(y)/SensorManager.GRAVITY_EARTH;
            }
			
			x = values[DATA_X] + cx;
			y = values[DATA_Y] + cy;
			z = values[DATA_Z] + cy;

            angle = Math.atan(Math.abs(y)/Math.abs(x));
            if(x > 0 && y > 0){
            	angle = 360 - Math.toDegrees(angle);
            }else if(x < 0 && y > 0){
            	angle = 180 + Math.toDegrees(angle);
            }else if(x < 0 && y < 0){
            	angle = 180 - Math.toDegrees(angle);
            }else if(x > 0 && y < 0){
            	angle = Math.toDegrees(angle);
            }
            
            if(angle < 15){
            	angle = angle - 25 + 360;
            }else{
            	angle = angle - 25;
            }
            
            if(y > 0 && y/SensorManager.GRAVITY_EARTH > maxBrakeG){
            	maxBrakeG = y/SensorManager.GRAVITY_EARTH;
            	maxBrakeAngle = angle;
            }
            
            if(y < 0 && y/SensorManager.GRAVITY_EARTH < maxAccelerationG){
            	maxAccelerationG = y/SensorManager.GRAVITY_EARTH;
            	maxAccelerationAngle = angle;
            }
            
            //Reverse it
            /*if(angle > 180){
            	angle = angle - 180;
            }else{
            	angle = angle + 180;
            }*/

			if (mView != null) {
                mView.invalidate();
            }
			
			if (lastUpdate == -1 || (curTime - lastUpdate) > 100) {
				lastUpdate = curTime;
				currentGTV.setText(String.format("%.2f", y/SensorManager.GRAVITY_EARTH));
				currentGTV.setTextColor(Color.BLUE);
				maxAccelerationGTV.setText(String.format("%.2f", maxAccelerationG));
				maxAccelerationGTV.setTextColor(Color.GREEN);
				maxBrakeGTV.setText(String.format("%.2f", maxBrakeG));
				maxBrakeGTV.setTextColor(Color.RED);
			}
		}
	}
	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	boolean result = super.onCreateOptionsMenu(menu);
    	menu.add(0, 0, 0, "Calibrate");
        return result;
    }
	
	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch (item.getItemId()) {
    	case 0:
    		cx = -x;
			cy = -y;
			cz = -z;
			break;
    	}
        return super.onOptionsItemSelected(item);
    }
	
	public void onClick(View v) {
		if (v == calibrateButton) {
			
		}
	}
	
	private class GForceView extends View {
        private Paint   mPaint = new Paint();
        public GForceView(Context context) {
            super(context);
        }
    
        @Override protected void onDraw(Canvas canvas) {
            
            int width = getWidth();
            int height = getHeight();
            int halfWidth = width / 2;
            int halfHeight = height / 2;
            int unitSize = (int)(halfWidth/maxUnits);
	    	
            for (int x = 1; x < 4; x++){
            	mPaint.setColor(Color.GRAY);
            	mPaint.setAlpha(75);
            	mPaint.setStyle(Paint.Style.STROKE);
            	mPaint.setStrokeWidth(2);

    	    	RectF oval = new RectF(halfWidth - (halfWidth/3) * x, 
        		halfHeight - (halfWidth/3) * x , 
        		halfWidth + (halfWidth/3) * x, 
        		halfHeight + (halfWidth/3) * x);
        		
    			canvas.drawArc(oval, 0, 360, true, mPaint);
            }
            
            mPaint.setStyle(Paint.Style.FILL);
	    	mPaint.setColor(Color.RED);
	    	mPaint.setAlpha(75);

	    	RectF oval = new RectF(halfWidth - (unitSize * maxBrakeG), 
    		halfHeight - (unitSize * maxBrakeG), 
    		halfWidth + (unitSize * maxBrakeG), 
    		halfHeight + (unitSize * maxBrakeG));
    		
			canvas.drawArc(oval, (float)maxBrakeAngle, 50, true, mPaint);
		
			mPaint.setColor(Color.GREEN);
			mPaint.setAlpha(75);

    		oval = new RectF(halfWidth - (unitSize * Math.abs(maxAccelerationG)), 
    		halfHeight - (unitSize  * Math.abs(maxAccelerationG)), 
    		halfWidth + (unitSize * Math.abs(maxAccelerationG)), 
    		halfHeight + (unitSize  * Math.abs(maxAccelerationG)));
    		
			canvas.drawArc(oval, (float)maxAccelerationAngle, 50, true, mPaint);
			
			mPaint.setColor(Color.BLUE);
            mPaint.setAlpha(60);  
			
			oval = new RectF(halfWidth - (unitSize * G), 
		    		halfHeight - (unitSize  * G), 
		    		halfWidth + (unitSize * G), 
		    		halfHeight + (unitSize  * G));
		    		
			canvas.drawArc(oval, (float)angle, 50, true, mPaint);
			
			Bitmap car = BitmapFactory.decodeResource(getResources(),R.drawable.car);
	    	canvas.drawBitmap(car, halfWidth-35, halfHeight-62, null);
	    	
        }
    }
	

}